﻿using MQTTnet.Client;
using MQTTnet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MQTTnet.Server;

namespace mqtt_demo
{
    public partial class Form1 : Form
    {
        private MqttFactory mqttFactory1 = null;
        private IMqttClient mqttClient1 = null;
        private MqttClientOptions mqttClientOptions = null;
        private bool isManualDisconnect = false; // 标记是否为手动断开连接
        private int reconnectDelay = 5000; // 重连延迟时间（毫秒）
        private CancellationTokenSource reconnectCancellationTokenSource = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            btnConnect.Enabled = true;
            btnSend.Enabled = false;
            btnClose.Enabled = false;
            btnSubscribe.Enabled = false;
            mqttFactory1 = new MqttFactory();
        }

        private async Task ConnectToMqttServer()
        {
            try
            {
                isManualDisconnect = false; // 重置手动断开标记

                // 取消之前的重连任务
                reconnectCancellationTokenSource?.Cancel();
                reconnectCancellationTokenSource = new CancellationTokenSource();

                MqttFactory mqttFactory = new MqttFactory();
                mqttClient1 = mqttFactory.CreateMqttClient();

                // 设置断开连接事件处理
                mqttClient1.DisconnectedAsync += OnMqttClientDisconnected;

                // 创建 MQTT 连接选项
                mqttClientOptions = new MqttClientOptionsBuilder()
                    .WithTcpServer(txtUrl.Text, Convert.ToInt32(txtPort.Text))
                    .WithClientId(txtCustId.Text)
                    .WithCleanSession(false) 
                    .Build();

                // 设置消息接收事件处理
                mqttClient1.ApplicationMessageReceivedAsync += e2 =>
                {
                    string topic = e2.ApplicationMessage.Topic;
                    string payload = Encoding.UTF8.GetString(e2.ApplicationMessage.Payload);
                    bool retained = e2.ApplicationMessage.Retain; // 获取 retained 状态
                    txtmsg.Invoke(new Action(() =>
                    {
                        int qosLevel = (int)e2.ApplicationMessage.QualityOfServiceLevel;
                        txtmsg.Text = $"[接收 (保存:{retained}, QoS:{qosLevel})] 主题：{topic} , 内容： {payload}\r\n"
                        + txtmsg.Text;
                    }));
                    return Task.CompletedTask;
                };

                var response = await mqttClient1.ConnectAsync(mqttClientOptions, CancellationToken.None);

                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = $"MQTT客户端已连接. IsConnected: [{mqttClient1.IsConnected}] resultCode:{response.ResultCode}\r\n" + txtmsg.Text;
                    UpdateConnectionStatus(true);
                }));
            }
            catch (Exception ex)
            {
                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = $"连接失败: {ex.Message}\r\n" + txtmsg.Text;
                    UpdateConnectionStatus(false);
                }));

                // 连接失败时自动重连
                if (!isManualDisconnect)
                {
                    await ScheduleReconnect();
                }
            }
        }

        private async Task OnMqttClientDisconnected(MqttClientDisconnectedEventArgs e)
        {
            txtmsg.Invoke(new Action(() =>
            {
                txtmsg.Text = $"MQTT连接断开: {e.ReasonString}\r\n" + txtmsg.Text;
                UpdateConnectionStatus(false);
            }));

            // 如果不是手动断开连接，则自动重连
            if (!isManualDisconnect)
            {
                await ScheduleReconnect();
            }
        }

        private async Task ScheduleReconnect()
        {
            try
            {
                // 等待一段时间后重连
                await Task.Delay(reconnectDelay, reconnectCancellationTokenSource.Token);

                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = $"尝试重新连接...\r\n" + txtmsg.Text;
                }));

                await ConnectToMqttServer();
            }
            catch (TaskCanceledException)
            {
                // 重连任务被取消（比如手动连接时）
                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = "重连任务已取消\r\n" + txtmsg.Text;
                }));
            }
            catch (Exception ex)
            {
                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = $"重连调度失败: {ex.Message}\r\n" + txtmsg.Text;
                }));

                // 重连调度失败，继续尝试重连
                if (!isManualDisconnect)
                {
                    await ScheduleReconnect();
                }
            }
        }

        private void UpdateConnectionStatus(bool isConnected)
        {
            btnConnect.Enabled = !isConnected;
            btnSend.Enabled = isConnected;
            btnClose.Enabled = isConnected;
            btnSubscribe.Enabled = isConnected;

            if (isConnected)
            {
                btnSend.Focus();
            }
            else
            {
                btnConnect.Focus();
            }
        }

        private async void btnConnect_Click(object sender, EventArgs e)
        {
            await ConnectToMqttServer();
        }

        private async void txtSend_Click(object sender, EventArgs e)
        {
            // 检查客户端是否已连接
            if (mqttClient1 == null || !mqttClient1.IsConnected)
            {
                txtmsg.Text = "客户端未连接，无法发送消息\r\n" + txtmsg.Text;
                return;
            }

            try
            {
                // 发布消息
                var applicationMessage = new MqttApplicationMessageBuilder()
                    .WithTopic(txtTopic.Text)
                    .WithPayload(txtSend.Text)
                    .WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce) // QoS = 1
                    .WithRetainFlag(true) // Retained = true
                    .Build();

                //异步发布消息
                await mqttClient1.PublishAsync(applicationMessage, CancellationToken.None);
                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = "消息已发送\r\n" + txtmsg.Text;
                }));
            }
            catch (Exception ex)
            {
                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = $"发送消息失败: {ex.Message}\r\n" + txtmsg.Text;
                }));
            }
        }

        private async void btnClose_Click(object sender, EventArgs e)
        {
            // 标记为手动断开，避免自动重连
            isManualDisconnect = true;

            // 取消重连任务
            reconnectCancellationTokenSource?.Cancel();

            // 检查客户端是否已连接
            if (mqttClient1 == null || !mqttClient1.IsConnected)
            {
                txtmsg.Text = "客户端未连接\r\n" + txtmsg.Text;
                UpdateConnectionStatus(false);
                return;
            }

            try
            {
                //断开连接
                await mqttClient1.DisconnectAsync();
                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = "连接已断开\r\n" + txtmsg.Text;
                    UpdateConnectionStatus(false);
                }));
            }
            catch (Exception ex)
            {
                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = $"断开连接失败: {ex.Message}\r\n" + txtmsg.Text;
                    UpdateConnectionStatus(false);
                }));
            }
        }

        private async void btnSubscribe_Click(object sender, EventArgs e)
        {
            // 检查客户端是否已连接
            if (mqttClient1 == null || !mqttClient1.IsConnected)
            {
                txtmsg.Text = "客户端未连接，无法订阅\r\n" + txtmsg.Text;
                return;
            }

            // 检查订阅主题是否为空
            if (string.IsNullOrWhiteSpace(subTopic.Text))
            {
                txtmsg.Text = "订阅主题不能为空\r\n" + txtmsg.Text;
                return;
            }

            try
            {
                //订阅主题的消息
                var mqttSubscribeOptions = mqttFactory1.CreateSubscribeOptionsBuilder()
                .WithTopicFilter(
                    f =>
                    {
                        f.WithTopic(subTopic.Text)
                         .WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce); // QoS = 1
                    })
                .Build();

                await mqttClient1.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);
                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = $"已订阅主题：{subTopic.Text}\r\n" + txtmsg.Text;
                }));
            }
            catch (Exception ex)
            {
                txtmsg.Invoke(new Action(() =>
                {
                    txtmsg.Text = $"订阅失败: {ex.Message}\r\n" + txtmsg.Text;
                }));
            }
        }

        private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            isManualDisconnect = true;
            reconnectCancellationTokenSource?.Cancel();

            if (mqttClient1 != null && mqttClient1.IsConnected)
            {
                await mqttClient1.DisconnectAsync();
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            txtmsg.Text = "";
        }
    }
}
